home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / telecomm / bbs / ctdlaux_src.lha / aux.c < prev    next >
C/C++ Source or Header  |  1994-01-29  |  27KB  |  1,041 lines

  1. /****************************************************************************
  2. *
  3. *  Aux Handler V1.0 (c)Copyright 1987,1989 Steve Drew.  All Rights Reserved.
  4. *
  5. *  Aux-Handler Ver. 1.2  21-Dec-1989
  6. *
  7. *  Steve Drew
  8. *  216 MacEwan Valley Mews N.W.
  9. *  Calgary, Ab. Canada.
  10. *
  11. *  |You may freely distribute this source as long as |
  12. *  |the Copyright notice is left intact.          |
  13. *
  14. *  Not for commercial use, unless approved by the author.
  15. ***************************************************************************/
  16. /*
  17. * Ver. 1.1 19-Oct-1989
  18. *
  19. * - Modified not to ignore null character when in RAW mode.
  20. * - slightly modified read_ser() to ensure all console style handling
  21. *   is ignored in raw mode.
  22. * - Added support for my AuxZmodem program (AZ). AZ sends AUX: an inhibit
  23. *   dos packet. AUX then cancels any reads to Serial port until AZ completes.
  24. *
  25. * Ver. 1.2 21-Dec-1989
  26. *
  27. * - don't have aux process hang around if SER: not available
  28. * - fix sec/micros in waitforchar()
  29. * - added carrier detection, if carrier disappears (was previously present )
  30. *   then throw away output, until carrier returns.
  31. *
  32. * ver 1.2a, 22-Apr-1992 did setparams to ensure XON/XOFF enabled.
  33. *
  34. * Ver 1.3   04-May-1992, added support for multi line cards.
  35. * Ver 1.3a  still trying to get multiline cards to work
  36. * Ver 1.3b  force XON flow control enabled.
  37. * Ver 3.42L23 Setup for SAS/C and for use with Citadel
  38. * Ver 3.42P15 Setup the serial port access like Citadel's
  39. *             so the GVP IOExtender would work...  Also added a
  40. *             Debug Port option...
  41. */
  42. #include "string.h"
  43. #include <libraries/dos.h>
  44. /*#include <ctype.h>*/
  45. #include <devices/console.h>
  46. #include <devices/serial.h>
  47. #include <devices/timer.h>
  48. #include <exec/types.h>
  49. #include <exec/ports.h>
  50. #include <exec/memory.h>
  51. #include <exec/tasks.h>
  52. #include <exec/nodes.h>
  53. #include <exec/lists.h>
  54. #include <exec/libraries.h>
  55. #include <exec/devices.h>
  56. #include <exec/io.h>
  57. #include <dos/dos.h>
  58. #include <dos/dosextens.h>
  59. #include <libraries/dos.h>
  60. #include <libraries/dosextens.h>
  61. #include <libraries/filehandler.h>
  62. #include "proto/all.h"
  63. #include "pragmas/dos_pragmas.h"
  64. #include "pragmas/exec_pragmas.h"
  65. #include "aux-debug.h"
  66.  
  67. int    atoi(char *);
  68. void _main(char *);
  69. void chk_params ( char *str );
  70. void chk_pend ( char *buf , struct DosPacket *pkt , struct Process *proc );
  71. int read_ser ( char *buf );
  72. void do_echo ( char *buf );
  73. void set_read(           void           );
  74. void write_ser ( char *buf , int len );
  75. void puts_ser ( char *buf , int len );
  76. int is_carrier ( void );
  77. int open_devices ( void );
  78. int open_serial ( void );
  79. int open_timer ( void );
  80. void close_devices ( void );
  81. void parse_startup ( char *str );
  82. void Aux_Debug(char *, int, int, int, int);
  83. void returnpktplain ( struct DosPacket *packet , struct Process *myproc );
  84. void returnpkt ( struct DosPacket *packet , struct Process *myproc , ULONG res1 , ULONG res2 );
  85. struct DosPacket *taskwait ( struct Process *myproc );
  86.  
  87. struct DosLibrary *DOSBase;
  88. struct DosLibrary *SYSBase;
  89.  
  90. #define DEVICE_NUMBER 0                 /* serial device unit number to use */
  91. #define DEVICE_NAME   "serial.device"   /* drive name for device            */
  92. typedef unsigned char u_char;
  93. #undef  BADDR
  94. #define BADDR(x)   ((APTR)((long)x << 2))
  95. #define AUX_ECHO             1
  96. #define AUX_CRLF             2
  97. #define AUX_RAW              4
  98. #define AUX_RPEND            8
  99. #define AUX_WAIT_FOR         16
  100. #define AUX_TYPEAHEAD_FULL     32
  101. #define AUX_SER_QUEUED        64
  102. #define AUX_MODEM               128
  103. #define DOECHO  (aux_stat & AUX_ECHO)
  104. #define DOCRLF  (aux_stat & AUX_CRLF)
  105. #define ISRAW    (aux_stat & AUX_RAW)
  106. #define ISRPEND (aux_stat & AUX_RPEND)
  107. #define ISWAITING (aux_stat & AUX_WAIT_FOR)
  108. #define ISBUFFULL (aux_stat & AUX_TYPEAHEAD_FULL)
  109. #define READINPROGRESS (aux_stat & AUX_SER_QUEUED)
  110. #define ISMODEM   (aux_stat & AUX_MODEM)
  111. #define AUXBUFSIZE              256  /* Same as CON: handler */
  112. #define MAXLINESIZE           254  /* save two for \n'\0'  */
  113. #define MYPORT_SIG  (1L << myport->mp_SigBit)
  114. #define READSER_SIG (1L << ReadSER->IOSer.io_Message.mn_ReplyPort->mp_SigBit)
  115. #define TIMER_SIG   (1L << Timer_Port->mp_SigBit)
  116. /* My Globals */
  117.  
  118. struct MsgPort     *mySerReadPort    = NULL;
  119. struct MsgPort     *mySerWritePort   = NULL;
  120. struct    IOExtSer   *ReadSER    = NULL;
  121. struct    IOExtSer   *WriteSER   = NULL;
  122.  
  123.  
  124. struct  timerequest *Timer;
  125. struct    MsgPort     *Timer_Port;
  126. struct  Task          *reader;
  127. int            aux_stat,  aux_avail,  in_len;
  128. u_char                in_c;
  129. long    device_number;
  130. char   *device_name;
  131. long    device_baud;
  132. char   *version =  "\0$VER: Citadel Aux Handler 3.42P15 (12.30.93)";
  133. void  _main(arg)
  134. char *arg;         /* default parameter */
  135.   {
  136.   struct Process    *myproc;         /* my process              */
  137.   struct DosPacket  *mypkt;          /* a pointer to the dos packet    */
  138.   struct DosPacket  *rdpkt;
  139.   struct DeviceNode *mynode;         /* our device node (parmpkt Arg3) */
  140.   struct FileHandle *fh;         /* a pointer to our file handle      */
  141.   struct MsgPort    *myport;
  142.   long          run = TRUE;    /* handler main loop flag      */
  143.   u_char            *ptr;        /* ptr for name translation       */
  144.   char          *name,*s;        /* ptr to name for open          */
  145.   int              aux_open = 0;    /* aux open count          */
  146.   char          auxbuf[AUXBUFSIZE];/* Our type ahead buffer      */
  147.   ULONG             signals;        /* signals that occurred in Wait  */
  148.   char              startup[100];
  149.   /* Initializing the handler */
  150.   DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0L);
  151.   SYSBase = (struct DosLibrary *)OpenLibrary("exec.library", 0L);
  152.   myproc            = (struct Process *)FindTask(0L);
  153.   Aux_Debug("Startup Message Wait...", (int)myproc, aux_stat, 0,FALSE);
  154.   mypkt             = taskwait(myproc);      /* Wait for my startup message */
  155.   rdpkt = mypkt;
  156.   mynode               = (struct DeviceNode *)BADDR(mypkt->dp_Arg3);
  157.   mynode->dn_Task     = &myproc->pr_MsgPort;
  158.   myport            = &myproc->pr_MsgPort;
  159.   returnpkt(mypkt, myproc, DOSTRUE, mypkt->dp_Res2);
  160.   in_len = aux_avail = aux_stat = 0;
  161.   reader = (struct Task *) 0;
  162.   s = (char *)BADDR(mypkt->dp_Arg2) ;  /* Arg2= BSTR to mountlist Startup */
  163.   if( s != NULL )
  164.     {
  165.     strncpy(startup,s+1,s[0]);
  166.     startup[s[0]] = '\0';
  167.     s = startup;
  168.     if (*s == '\"')
  169.       {
  170.       s++;
  171.       s[strlen(s)-1]= '\0' ;
  172.       };
  173.     }
  174.   else startup[0] = '\0';
  175.   /* set defaults */
  176.   device_name   = DEVICE_NAME;
  177.   device_number = DEVICE_NUMBER;
  178.   device_baud   = 0;
  179.   parse_startup(s);
  180.   /* done initial stuff, now for some work */
  181.   Aux_Debug(device_name, device_number, device_baud, 0,FALSE);
  182.   while(run)
  183.     {
  184.     if (aux_open)
  185.       {
  186.       /* then wait for read char or new action */
  187.       if (READINPROGRESS)
  188.       signals = Wait( MYPORT_SIG | READSER_SIG | TIMER_SIG );
  189.       else
  190.       signals = Wait( MYPORT_SIG );
  191.       if (signals & TIMER_SIG)
  192.         {
  193.         WaitIO((struct IORequest *)Timer);
  194.         Aux_Debug("Timer SIG...", signals, aux_stat, 0,FALSE );
  195.         aux_stat &= ~AUX_WAIT_FOR;
  196.         rdpkt->dp_Res1 = DOSFALSE;
  197.         returnpktplain(rdpkt,myproc);
  198.  
  199.         }
  200.       if ((signals & READSER_SIG) && CheckIO((struct IORequest *)ReadSER))
  201.         {
  202.         Aux_Debug("READSER SIG...", signals, aux_stat, 0,FALSE);
  203.         read_ser(auxbuf);
  204.         chk_pend(auxbuf,rdpkt,myproc);
  205.  
  206.         }
  207.       if (signals & MYPORT_SIG)
  208.         {
  209.         Aux_Debug("MYPORT_SIG...",signals,aux_stat,0,FALSE);
  210.         mypkt = taskwait(myproc);
  211.  
  212.         }
  213.       else    /* no new dospackets */
  214.       continue;
  215.  
  216.       }
  217.     else         /* only port at the moment is myport */
  218.     mypkt = taskwait(myproc);
  219.     Aux_Debug("dp_type...", signals, (int)mypkt, (int)mypkt->dp_Type,FALSE);
  220.     switch(mypkt->dp_Type)
  221.       {
  222.       /* find what action to perform */
  223.       case MODE_OLDFILE:
  224.       case MODE_NEWFILE:
  225.       /*
  226.       I allow for multiple writers. But only one process to read
  227.       at a time.
  228.       */
  229.       if (!aux_open)
  230.         {
  231.         /* first time here we open the devices */
  232.         if (open_devices() == 0)
  233.           {
  234.           Aux_Debug("Error... open_device failed", 0, 0, 0,FALSE);
  235.           returnpkt(mypkt, myproc, DOSFALSE, ERROR_OBJECT_IN_USE);
  236.           run = 0;   /* don't hang arround */
  237.           break;
  238.  
  239.           }
  240.  
  241.         }
  242.       aux_open++;
  243.       /*
  244.       * if baud specified in Startup message, set it here, else
  245.       * check filename for SET/ param later below.
  246.       */
  247.       /*            xxx            */
  248.       /* get file name and Upper case it */
  249.       ptr = (u_char *)BADDR(mypkt->dp_Arg3);
  250.       name = (char *)AllocMem((long)*ptr + 1, MEMF_PUBLIC);
  251.       movmem(ptr+1, name, *ptr);
  252.       name[*ptr] = '\0';
  253.       for (s = name; *s; ++s)
  254.         {
  255.         *s = (*s >= 'a' && *s <= 'z') ? (*s - 'a' + 'A') : *s;
  256.         };
  257.       /*
  258.       This is a Hack to allow a bail out of a NEWCLI
  259.       that is using the AUX. By doing say an echo >AUX:ENDCLI
  260.       from another process the reader (being the NEWCLI)
  261.       will be sent a ENDCLI command.
  262.       */
  263.       Aux_Debug(name, ISRPEND, aux_stat, 0,FALSE);
  264.       for (s = name; *s; ++s) if (*s == ':') break;
  265.       if (!strcmp(s,":ENDCLI") && (ISRPEND))
  266.         {
  267.         strcpy((char *)rdpkt->dp_Arg2,"ENDCLI\n");
  268.         rdpkt->dp_Res1 = 7L;
  269.         returnpktplain(rdpkt, myproc);
  270.         aux_stat &= ~AUX_RPEND;
  271.  
  272.         }
  273.       else
  274.       chk_params(name);
  275.       FreeMem(name, (long)*ptr +1);
  276.       fh = (struct FileHandle  *)BADDR(mypkt->dp_Arg1);
  277.       fh->fh_Arg1 = DOSTRUE;
  278.       fh->fh_Port = (struct MsgPort *)DOSTRUE;
  279.       if (mypkt->dp_Type == MODE_OLDFILE)
  280.         {
  281.         struct MsgPort *port;
  282.         port = mypkt->dp_Port;
  283.         if (reader && port->mp_SigTask != reader)
  284.           {
  285.           returnpkt(mypkt, myproc, DOSFALSE, ERROR_OBJECT_IN_USE);
  286.           --aux_open;
  287.           break;
  288.  
  289.           }
  290.         reader = port->mp_SigTask;
  291.         fh->fh_Arg1 = (long)port->mp_SigTask;
  292.  
  293.         }
  294.       returnpkt(mypkt, myproc, DOSTRUE, mypkt->dp_Res2);
  295.       break;
  296.       case ACTION_READ:
  297.       set_read();
  298.       rdpkt = mypkt;
  299.       aux_stat |= AUX_RPEND;
  300.       do_echo(auxbuf);
  301.       chk_pend(auxbuf,rdpkt,myproc);
  302.       Aux_Debug("ACTION_READ", 0, aux_stat, 0,FALSE);
  303.       break;
  304.       case ACTION_WRITE:
  305.       write_ser((char *)mypkt->dp_Arg2,(int)mypkt->dp_Arg3);
  306.       mypkt->dp_Res1 = mypkt->dp_Arg3;  /* tell em we wrote them all */
  307.       returnpktplain(mypkt, myproc);
  308.       Aux_Debug("ACTION_WRITE", 0, aux_stat, 0,FALSE);
  309.       break;
  310.       case ACTION_WAIT_CHAR:
  311.       /* just queue up to wait for data */
  312.       set_read();
  313.       rdpkt = mypkt;
  314.       aux_stat |= AUX_WAIT_FOR;
  315.       if (rdpkt->dp_Arg1 >= 1000000L)
  316.         {
  317.         Timer->tr_time.tv_secs   = rdpkt->dp_Arg1 / 1000000L;
  318.         Timer->tr_time.tv_micro  = rdpkt->dp_Arg1 % 1000000L;
  319.  
  320.         }
  321.       else
  322.         {
  323.         Timer->tr_time.tv_secs   = 0L;
  324.         Timer->tr_time.tv_micro  = rdpkt->dp_Arg1;
  325.  
  326.         }
  327.       SendIO((struct IORequest *)Timer);
  328.       chk_pend(auxbuf,rdpkt,myproc);
  329.       Aux_Debug("ACTION_WAIT_CHAR", 0, aux_stat, 0,FALSE);
  330.       break;
  331.       case ACTION_SCREEN_MODE:
  332.       if (mypkt->dp_Arg1)
  333.         {
  334.         aux_stat |= AUX_RAW;
  335.         aux_stat &= ~AUX_ECHO;
  336.  
  337.         }
  338.       else
  339.         {
  340.         aux_stat &= ~AUX_RAW;
  341.         aux_stat |= AUX_ECHO;
  342.  
  343.         }
  344.       chk_pend(auxbuf,rdpkt,myproc);
  345.       returnpkt(mypkt, myproc, DOSTRUE, mypkt->dp_Res2);
  346.       Aux_Debug("ACTION_SCREEN_MODE", 0, aux_stat, 0,FALSE);
  347.       break;
  348.       case ACTION_END:
  349.       if (--aux_open == 0)
  350.         {
  351.         run = 0;
  352.         close_devices();
  353.         reader = (struct Task *) 0L;
  354.  
  355.         }
  356.       returnpkt(mypkt, myproc, DOSTRUE, mypkt->dp_Res2);
  357.       Aux_Debug("ACTION_END", 0, aux_stat, 0,FALSE);
  358.       break;
  359.       case ACTION_INHIBIT:
  360.       if (READINPROGRESS)
  361.         {
  362.         AbortIO((struct IORequest *)ReadSER);
  363.         Wait(READSER_SIG);
  364.         WaitIO((struct IORequest *)ReadSER);
  365.         aux_stat &= ~AUX_SER_QUEUED;
  366.  
  367.         }
  368.       returnpkt(mypkt, myproc, DOSTRUE, mypkt->dp_Res2);
  369.       Aux_Debug("ACTION_INHIBIT", 0, aux_stat, 0,FALSE);
  370.       break;
  371.       default:
  372.       returnpkt(mypkt, myproc, DOSFALSE, ERROR_ACTION_NOT_KNOWN);
  373.       Aux_Debug("Default...", 0, aux_stat, 0,FALSE);
  374.       break;
  375.  
  376.       }
  377.  
  378.     }
  379.   /* end while */
  380.   mynode->dn_Task = FALSE;
  381.   CloseLibrary((struct Library *)DOSBase);
  382.   CloseLibrary((struct Library *)SYSBase);
  383.   }
  384. /*
  385. Allows some flexibilty to control the port.
  386. Can dynamically change CRLF translation,
  387. Echo or RAW mode on/off.
  388. */
  389. void chk_params(str)
  390. char *str;
  391.   {
  392.   char *ptr, *s;
  393.   int param, i=1;
  394.   Aux_Debug(str, 0, 0, 0,TRUE);
  395.   for (s = str; *s; ++s) if (*s == ':') break;
  396.   if (strncmp(str,":SET/",5)) return;
  397.   ptr = str + 8;
  398.   while(i)
  399.     {
  400.     for (s = ptr; *ptr && *ptr != '/'; ++ptr);
  401.     if (*ptr == '\0') i = 0;
  402.     *ptr = '\0';
  403.     str = s+2;
  404.     if (ptr > str)
  405.       {
  406.       switch (*s)
  407.         {
  408.         case 'E':
  409.         param = AUX_ECHO;
  410.         break;
  411.         case 'C':
  412.         param = AUX_CRLF;
  413.         break;
  414.         case 'R':
  415.         param = AUX_RAW;
  416.         break;
  417.         default:
  418.         param = 0;
  419.         break;
  420.  
  421.         }
  422.       if (*str == 'O')
  423.         {
  424.         if (*(str+1) == 'N')  aux_stat |= param;
  425.         else
  426.         if (*(str+1) == 'F') aux_stat &= ~param;
  427.  
  428.         }
  429.  
  430.       }
  431.     ++ptr;
  432.  
  433.     }
  434.  
  435.   }
  436. /*
  437. Check our buf to see if we have a line to return yet. Or if raw mode
  438. give 'em all we got.
  439. */
  440. void chk_pend(buf,pkt,proc)
  441. char         *buf;
  442. struct DosPacket *pkt;
  443. struct Process   *proc;
  444.   {
  445.   char *p;
  446.   int i=0;
  447.   Aux_Debug("chk_pend",in_len, aux_stat, aux_avail,FALSE);
  448.   if ((in_len && (ISRAW)) || aux_avail)
  449.     {
  450.     if (ISWAITING)
  451.       {
  452.       aux_stat &= ~AUX_WAIT_FOR;      /* clear the wait_for */
  453.       pkt->dp_Res1 = DOSTRUE;
  454.       AbortIO((struct IORequest *)Timer);
  455.       Wait(TIMER_SIG);
  456.       WaitIO((struct IORequest *)Timer);
  457.       returnpktplain(pkt,proc);
  458.  
  459.       }
  460.     else if (ISRPEND)
  461.       {
  462.       aux_stat &= ~AUX_RPEND;     /* clear the pending read  */
  463.       if (ISRAW)
  464.         {
  465.         aux_avail = 0;         /* since we're sending all */
  466.  
  467.         }
  468.       else
  469.       --aux_avail;
  470.       /* if in_len is zero, then aux_avail must of been
  471.       set up to force us here to reply with Res1 = 0;
  472.       thus actually returning an EOF.
  473.       */
  474.       if (in_len)
  475.         {
  476.         for (i = 1,p = (char *) pkt->dp_Arg2;
  477.         ((p[i-1] = buf[i-1]) != '\n' || ISRAW) &&
  478.         i < pkt->dp_Arg3 && i < in_len; ++i) ;
  479.         /* reader asked for less than 256 chars but no cr
  480.         was found. If not in raw mode then bump avail back
  481.         up since we still have the remaining CR terminated
  482.         line in buf[].
  483.         */
  484.         if (p[i-1] != '\n' && !(ISRAW))
  485.           {
  486.           ++aux_avail;
  487.  
  488.           }
  489.  
  490.         }
  491.       in_len -= i;
  492.       movmem(buf+i,buf,in_len);
  493.       set_read();
  494.       pkt->dp_Res1 = (long)i;
  495.       Aux_Debug(buf,in_len, aux_stat, aux_avail,TRUE);
  496.       returnpktplain(pkt,proc);
  497.  
  498.       }
  499.  
  500.     }
  501.  
  502.   }
  503. /*
  504. Only called here if there really is a character waiting to be read.
  505. */
  506. read_ser(buf)
  507. char *buf;
  508.   {
  509.   char c;
  510.   int ignore = 1;
  511.   if( ReadSER == NULL )
  512.     {
  513.     if( reader )Signal(reader, SIGBREAKF_CTRL_C);
  514.     return 1;
  515.     };
  516.   Aux_Debug("read_ser before", in_c, aux_stat, ReadSER->IOSer.io_Error,FALSE);
  517.   WaitIO((struct IORequest *)ReadSER);
  518.   aux_stat &= ~AUX_SER_QUEUED;
  519.   c = in_c;
  520.   Aux_Debug("read_ser after", c, aux_stat, ReadSER->IOSer.io_Error,FALSE);
  521.   /* ^C typed so immediately send the signal */
  522.   if (c == 3)
  523.     {
  524.     if (reader)
  525.     Signal(reader,SIGBREAKF_CTRL_C);
  526.  
  527.     }
  528.   /*
  529.   * in raw mode, no filtering is done.
  530.   */
  531.   if (ISRAW)
  532.     {
  533.     if (in_len < MAXLINESIZE) buf[in_len++] = c;
  534.     set_read();
  535.     return(1);
  536.  
  537.     }
  538.   switch(c)
  539.     {
  540.     case  3:                /* already done above */
  541.     break;
  542.     case  4:        /* ^D, send the signal if there is a reader */
  543.     if (reader)
  544.     Signal(reader,SIGBREAKF_CTRL_D);
  545.     break;
  546.     case  6:                /* ^F, send the signal if there is a reader */
  547.     if (reader)
  548.     Signal(reader,SIGBREAKF_CTRL_F);
  549.     break;
  550.     case 28:        /* ^\ so wipe out line and force EOF      */
  551.     in_len = 0;
  552.     ++aux_avail;
  553.     break;
  554.     case 13:        /* Always convert ^M to newline chara */
  555.     case 10:
  556.     c = 10;
  557.     ignore = 0;
  558.     ++aux_avail;
  559.     break;
  560.     case 8:                /* BS */
  561.     case 127:        /* DEL */
  562.     if (in_len && buf[in_len-1] != '\n')
  563.       {
  564.       --in_len;
  565.       write_ser("\b \b",3);
  566.  
  567.       }
  568.     break;
  569.     case 24:         /* ^X */
  570.     case 21:        /* ^U */
  571.     while(in_len && buf[in_len-1] != '\n')
  572.       {
  573.       --in_len;
  574.       write_ser("\b \b",3);
  575.  
  576.       }
  577.     break;
  578.     case 18:                /* ^R  */
  579.     if (ISRPEND)
  580.       {
  581.       write_ser("\n",1);
  582.       do_echo(buf);
  583.  
  584.       }
  585.     break;
  586.     case 27:        /* <ESC> */
  587.     break;
  588.     default:
  589.     ignore = 0;
  590.     break;
  591.  
  592.     }
  593.   /*
  594.   * is it, a valid character
  595.   */
  596.   if (ignore == 0)
  597.     {
  598.     /*
  599.     * Length is already at maximum, forget about this character
  600.     * and Beep the user.
  601.     */
  602.     if (c != '\n' && in_len >= MAXLINESIZE)
  603.       {
  604.       write_ser("\007",1);
  605.  
  606.       }
  607.     /*
  608.     * normal case, save and echo if applicable
  609.     */
  610.     else
  611.       {
  612.       buf[in_len++] = c;
  613.       /*
  614.       * don't echo unless aux process has caught upto us.
  615.       * ie, simulate VMS terminal handler rather than unix or
  616.       * amigados con:. This makes it nicer to typeahead the next
  617.       * command without causing the output from the current command
  618.       * to stop, thus pausing the current command.
  619.       */
  620.       if (DOECHO)
  621.         {
  622.         if (ISRPEND) write_ser(&c,1);
  623.  
  624.         }
  625.  
  626.       }
  627.  
  628.     }
  629.   set_read();
  630.  
  631.   }
  632. /*
  633. * Now ready to echo first line of typeahead, or possible retyping
  634. * due to ^R command.
  635. */
  636. void do_echo(buf)
  637. char *buf;
  638.   {
  639.   int i;
  640.   if (DOECHO)
  641.     {
  642.     for(i = 0; i < in_len ; ++i)
  643.       {
  644.       if (buf[i] == '\n')
  645.         {
  646.         ++i;
  647.         break;
  648.  
  649.         }
  650.  
  651.       }
  652.     if (i) write_ser(buf,i);
  653.  
  654.     }
  655.  
  656.   }
  657. /*
  658. Start a asynchronous Read request
  659. */
  660. void set_read()
  661.   {
  662.   Aux_Debug("set_read", in_c, aux_stat, READINPROGRESS,FALSE);
  663.   if (!READINPROGRESS)
  664.     {
  665.     ReadSER->IOSer.io_Length  = 1L;
  666.     ReadSER->IOSer.io_Command = CMD_READ;
  667.     ReadSER->IOSer.io_Data    = (APTR) &in_c;
  668.     SendIO((struct IORequest *)ReadSER);
  669.     aux_stat |= AUX_SER_QUEUED;
  670.  
  671.     }
  672.  
  673.   }
  674. void write_ser(buf,len)
  675. char *buf;
  676. int len;
  677.   {
  678.   int i,j;
  679.   Aux_Debug("write_ser", (int)buf, DOCRLF, len,FALSE);
  680.   buf[len] = '\0';
  681.   Aux_Debug(buf,len,0,0,TRUE);
  682.   if (DOCRLF)
  683.     {
  684.     /*
  685.     * rather than call the serial device for each character, write all
  686.     * characters upto newline then insert <CR><LF> and continue.
  687.     */
  688.     for(j=i=0; i < len; ++i)
  689.       {
  690.       if (buf[i] == '\n')
  691.         {
  692.         puts_ser(&buf[j],(i-j));
  693.         puts_ser("\r\n",2); /* ensure <CR><LF> order */
  694.         j = i+1;
  695.  
  696.         }
  697.  
  698.       }
  699.     if (j < len)
  700.     puts_ser(&buf[j],(len-j));
  701.  
  702.     }
  703.   else
  704.     {
  705.     puts_ser(buf,len);
  706.  
  707.     }
  708.  
  709.   }
  710. void puts_ser(buf,len)
  711. char *buf;
  712. int len;
  713.   {
  714.   /*
  715.   * If carrier was present and now is'nt then discard characters until
  716.   * carrier returns
  717.   */
  718.   if( WriteSER == NULL)return;
  719.   Aux_Debug("puts_ser", (int)buf, ISMODEM, len,FALSE);
  720.   if (len)
  721.     {
  722.     if (is_carrier() || !ISMODEM)
  723.       {
  724.       WriteSER->IOSer.io_Command = CMD_WRITE;
  725.       WriteSER->IOSer.io_Length = (long)len;
  726.       WriteSER->IOSer.io_Data = (APTR) buf;
  727.       DoIO((struct IORequest *)WriteSER);
  728.       Aux_Debug("puts_ser:result", buf[0],WriteSER->IOSer.io_Error, len,FALSE);
  729.  
  730.       }
  731.  
  732.     }
  733.  
  734.   }
  735. /*
  736. * return 0 if nocarrier
  737. */
  738. is_carrier()
  739.   {
  740.   if( WriteSER == NULL ) return (0);
  741.   WriteSER->IOSer.io_Command = SDCMD_QUERY;
  742.   DoIO((struct IORequest *)WriteSER);
  743.   Aux_Debug("is_carrier", WriteSER->io_Status, aux_stat, WriteSER->IOSer.io_Error,FALSE);
  744.   if (!(WriteSER->io_Status & 0x20))
  745.     {
  746.     aux_stat |= AUX_MODEM;
  747.     return(1);
  748.  
  749.     }
  750.   return(0);
  751.  
  752.   }
  753. open_devices()
  754.   {
  755.   ReadSER    = WriteSER = NULL;
  756.   Timer_Port = NULL;
  757.   Timer      = NULL;
  758.   aux_stat = AUX_ECHO | AUX_CRLF;  /* set the default */
  759.   if (open_serial() && open_timer())
  760.     {
  761.     set_read();
  762.     return(1);
  763.  
  764.     }
  765.   close_devices();
  766.   return(0);
  767.  
  768.   }
  769. /*
  770. * open serial device
  771. */
  772. open_serial()
  773.   {
  774.   if( (mySerReadPort = CreatePort(NULL,NULL)) != NULL)
  775.     {
  776.     Aux_Debug("open_serial",0 ,(int)mySerReadPort ,0 ,FALSE);
  777.     ReadSER = (struct IOExtSer *)CreateExtIO(mySerReadPort, sizeof(struct IOExtSer));
  778.     if( ReadSER != NULL )
  779.       {
  780.       Aux_Debug("open_serial",1 ,(int)ReadSER,0 ,FALSE);
  781.       if( (mySerWritePort = CreatePort(NULL,NULL)) != NULL  )
  782.         {
  783.         Aux_Debug("open_serial",2 ,(int)mySerWritePort,0 ,FALSE);
  784.         WriteSER = (struct IOExtSer *)CreateExtIO(mySerWritePort, sizeof(struct IOExtSer));
  785.         if( WriteSER  != NULL)
  786.           {
  787.           ReadSER->io_SerFlags = SERF_RAD_BOOGIE|SERF_SHARED|SERF_XDISABLED|SERF_7WIRE;
  788.           Aux_Debug("open_serial",3 ,(int)WriteSER,0 ,FALSE);
  789.           if ( !OpenDevice(device_name,device_number,(struct IORequest*)ReadSER,NULL) )
  790.             {
  791.             WriteSER->io_SerFlags = SERF_RAD_BOOGIE|SERF_SHARED|SERF_XDISABLED|SERF_7WIRE;
  792.             Aux_Debug("open_serial",4 ,(int)ReadSER->IOSer.io_Error,0 ,FALSE);
  793.             if ( !OpenDevice(device_name,device_number,(struct IORequest *)WriteSER,NULL) )
  794.               {
  795.               Aux_Debug("open_serial",5 ,(int)WriteSER->IOSer.io_Error ,0 ,FALSE);
  796.               return 1;
  797.  
  798.               }
  799.             else
  800.               {
  801.               CloseDevice((struct IORequest *)ReadSER);  /* extra thing to do if error */
  802.  
  803.               };
  804.  
  805.             };
  806.  
  807.           };
  808.  
  809.         };
  810.  
  811.       };
  812.  
  813.     };
  814.   Aux_Debug("open_serial",-1 ,(int)mySerWritePort, (int)mySerReadPort ,FALSE);
  815.   if( WriteSER      )DeleteExtIO((struct IORequest *)WriteSER);
  816.   if( mySerWritePort)DeletePort(mySerWritePort);
  817.   if( ReadSER       )DeleteExtIO((struct IORequest *)ReadSER);
  818.   if( mySerReadPort )DeletePort(mySerReadPort);
  819.   WriteSER       = NULL;
  820.   ReadSER        = NULL;
  821.   mySerWritePort = NULL;
  822.   mySerReadPort  = NULL;
  823.   return(0);
  824.  
  825.   }
  826. /*
  827. * Open Timer.device
  828. */
  829. open_timer()
  830.   {
  831.   if (Timer_Port = CreatePort (NULL, NULL))
  832.     {
  833.     Aux_Debug("open_timer",0 ,0 ,0 ,FALSE);
  834.     if ((Timer = (struct  timerequest *)
  835.     CreateExtIO (Timer_Port, (long) sizeof (*Timer))) != NULL )
  836.       {
  837.       Aux_Debug("open_timer",1 ,0 ,0 ,FALSE);
  838.       if (!(OpenDevice (TIMERNAME, UNIT_VBLANK, (struct IORequest *)Timer, 0L)))
  839.         {
  840.         Timer->tr_node.io_Command = TR_ADDREQUEST;
  841.         Timer->tr_node.io_Flags = 0;
  842.         Timer->tr_node.io_Error = 0;
  843.         Aux_Debug("open_timer",2 ,0 ,0 ,FALSE);
  844.         return(1);
  845.  
  846.         }
  847.  
  848.       }
  849.  
  850.     }
  851.   Aux_Debug("open_timer",-1 ,(int)Timer_Port ,(int)Timer ,FALSE);
  852.   Timer->tr_node.io_Device = 0;
  853.   return(0);
  854.  
  855.   }
  856. void close_devices()
  857.   {
  858.   if (READINPROGRESS)
  859.     {
  860.     AbortIO((struct IORequest *)ReadSER);
  861.     Wait(READSER_SIG);
  862.     WaitIO((struct IORequest *)ReadSER);
  863.  
  864.     }
  865.   if( ReadSER       )
  866.     {
  867.     CloseDevice((struct IORequest *)ReadSER);
  868.     DeleteExtIO((struct IORequest *)ReadSER);
  869.  
  870.     };
  871.   if( mySerReadPort )DeletePort(mySerReadPort);
  872.   if (WriteSER)
  873.     {
  874.     CloseDevice((struct IORequest *)WriteSER);
  875.     DeleteExtIO((struct IORequest *)WriteSER);
  876.  
  877.     }
  878.   if( mySerWritePort)DeletePort(mySerWritePort);
  879.   if (Timer)
  880.     {
  881.     if (Timer->tr_node.io_Device)
  882.     CloseDevice ((struct IORequest *)Timer);
  883.     DeleteExtIO ((struct IORequest *)Timer);
  884.  
  885.     }
  886.   WriteSER       = NULL;
  887.   ReadSER        = NULL;
  888.   mySerWritePort = NULL;
  889.   mySerReadPort  = NULL;
  890.   if (Timer_Port)
  891.   DeletePort(Timer_Port);
  892.   Timer_Port = NULL;
  893.   Aux_Debug("close_device",0 ,0 ,0 ,FALSE);
  894.  
  895.   }
  896. /*
  897. * in mountlist startup allow:
  898. *
  899. * startup = "DEVICE:serial.device/UNIT:0/BAUD:2400"
  900. */
  901. void parse_startup(str)
  902. char *str;
  903.   {
  904.   char *s = str;
  905.   char *arg,*value;
  906.   int more = 1;
  907.   if( s == NULL)return;
  908.   while(more)
  909.     {
  910.     for(arg = s; *s; ++s) if (*s == ':') break;
  911.     if (!*s) break;
  912.     *s = '\0';
  913.     ++s;
  914.     for(value = s; *s; ++s) if (*s == '/') break;
  915.     if (!*s) more = 0;
  916.     *s = '\0';
  917.     ++s;
  918.     if (strcmp("DEVICE",arg) == 0)
  919.       {
  920.       device_name = value;
  921.  
  922.       }
  923.     else if (strcmp("UNIT",arg) == 0)
  924.       {
  925.       device_number = atoi(value);
  926.  
  927.       }
  928.     else if (strcmp("BAUD",arg) == 0)
  929.       {
  930.       device_baud = atoi(arg);
  931.  
  932.       }
  933.  
  934.     }
  935.  
  936.   }
  937.  
  938. void Aux_Debug(msg, int1, int2, int3, flag)
  939. char *msg;             /* the message to send */
  940. int  int1, int2, int3, flag; /* various integer data to send */
  941.   {
  942.   struct MsgPort *port;
  943.   char *mymessage;
  944.   struct debugmsg *temp;
  945.   Forbid();
  946.   port = FindPort(AUXDEBUGPORT);  /* check to see if we have a port...*/
  947.   Permit();
  948.   if( !port )return;  /* if no port, just exit */
  949.   temp      = (struct debugmsg *)AllocMem(sizeof(struct debugmsg),0);
  950.   if(!temp) return;
  951.   mymessage = (char *)AllocMem(strlen(msg)+1,0);  /* dynamic sizing */
  952.   if( mymessage == NULL)
  953.     {
  954.     FreeMem(temp, sizeof(struct debugmsg));
  955.     return;
  956.     };
  957.   strcpy(mymessage,msg);
  958.   temp->msg   = mymessage;
  959.   temp->a     = int1;
  960.   temp->b     = int2;
  961.   temp->c     = int3;
  962.   temp->flag  = flag;
  963. /*
  964. ** Setup the Message itself
  965. */
  966. temp->ipc_Msg.mn_Node.ln_Type = NT_MESSAGE;
  967. temp->ipc_Msg.mn_Length = sizeof(struct debugmsg);
  968. temp->ipc_Msg.mn_ReplyPort = NULL;
  969.  
  970. /* safe send of a message.  If Port exists, we send the
  971. ** packet and forget about it.  If the Port does not exist
  972. ** we forget that the message even existed...
  973. */
  974.   Forbid();
  975.   port = FindPort(AUXDEBUGPORT);
  976.   if( port )
  977.     {
  978.     PutMsg(port,(struct Message *)temp);
  979.     }
  980.   else
  981.     {
  982.     FreeMem(temp->msg,strlen(msg)+1);
  983.     FreeMem(temp, sizeof(struct debugmsg));
  984.     }
  985.   Permit();
  986. /*
  987. ** we do not wait for the message reply, in this case there is
  988. ** no reply done and all memmory is deallocated in the reciever.
  989. */
  990.   }
  991. /* returnpkt() - packet support routine
  992. * here is the guy who sends the packet back to the sender...
  993. *
  994. * (I modeled this just like the BCPL routine [so its a little redundant] )
  995. */
  996.  
  997. void returnpktplain(packet, myproc)
  998. struct DosPacket *packet;
  999. struct Process *myproc;
  1000.   {
  1001.   returnpkt(packet, myproc, packet->dp_Res1, packet->dp_Res2);
  1002.  
  1003.   }
  1004. void
  1005. returnpkt(packet, myproc, res1, res2)
  1006. struct DosPacket *packet;
  1007. struct Process *myproc;
  1008. ULONG  res1, res2;
  1009.   {
  1010.   struct Message *mess;
  1011.   struct MsgPort *replyport;
  1012.   packet->dp_Res1          = res1;
  1013.   packet->dp_Res2          = res2;
  1014.   replyport                = packet->dp_Port;
  1015.   mess                     = packet->dp_Link;
  1016.   packet->dp_Port          = &myproc->pr_MsgPort;
  1017.   mess->mn_Node.ln_Name    = (char *) packet;
  1018.   mess->mn_Node.ln_Succ    = NULL;
  1019.   mess->mn_Node.ln_Pred    = NULL;
  1020.   PutMsg(replyport, mess);
  1021.   Aux_Debug("Return Packet",(int)packet ,res1 ,res2, FALSE );
  1022.  
  1023.   }
  1024. /*
  1025. * taskwait() ... Waits for a message to arrive at your port and
  1026. *   extracts the packet address which is returned to you.
  1027. */
  1028. struct DosPacket *
  1029. taskwait(myproc)
  1030. struct Process *myproc;
  1031.   {
  1032.   struct MsgPort *myport;
  1033.   struct Message *mymess;
  1034.   myport = &myproc->pr_MsgPort;
  1035.   WaitPort(myport);
  1036.   mymess = GetMsg(myport);
  1037.   Aux_Debug("taskwait",(int)mymess ,0 ,0, FALSE );
  1038.   return((struct DosPacket *)mymess->mn_Node.ln_Name);
  1039.  
  1040.   }
  1041.